﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;


//documentation warning - no need to document unit tests
#pragma warning disable 1591
namespace SQLToolbox.Lib.UnitTests
{
	/// <summary>
	/// Write the summary for the test class here.
	/// </summary>
	[TestFixture]
	public class PriorityQueueTest
	{

		public bool peek_checkPQ<T>(PriorityQueue<T> pq)
		{
			IComparer<T> c = pq.Comparer;

			for (int i = 0; i < pq.Count; i++)
			{
				int child = 2 * i + 1;
				if (child >= pq.Count)
					break;

				if (c.Compare(pq[i], pq[child]) > 0)
					return false;

				++child;
				if (child >= pq.Count)
					break;

				if (c.Compare(pq[i], pq[child]) > 0)
					return false;
			}
			return true;
		}

		public bool pop_checkPQ<T>(PriorityQueue<T> pq)
		{
			IComparer<T> c = pq.Comparer;

			while (pq.Count > 1)
			{
				T pop = pq.Dequeue();
				if (c.Compare(pop, pq.Peek()) > 0)
					return false;
			}

			return true;
		}

		public bool pop_fullcheckPQ<T>(PriorityQueue<T> pq)
		{
			IComparer<T> c = pq.Comparer;

			while (pq.Count > 1)
			{
				T pop = pq.Dequeue();
				for (int i = 0; i < pq.Count; ++i)
				{
					if (c.Compare(pop, pq[i]) > 0)
						return false;
				}
			}

			return true;
		}

		public class abscomparer : IComparer<int>
		{
			public int Compare(int x, int y)
			{
				return Math.Abs(x) - Math.Abs(y);
			}
		}

		[Test]
		public void p1()
		{

			PriorityQueue<int> pq = new PriorityQueue<int>(new abscomparer());
			int s = 0;
			pq.Enqueue(3); s++;
			pq.Enqueue(2); s++;
			pq.Enqueue(2); s++;
			pq.Enqueue(4); s++;
			pq.Enqueue(1); s++;
			pq.Enqueue(-5); s++;
			pq.Enqueue(-3); s++;

			pq.Sort(new abscomparer());
			pq.AdjustHeap();

			pq.Sort();
			pq.AdjustHeap();

			pq.EnqueueRange(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
			s += 10;

			Assert.AreEqual(s, pq.Count);

			Assert.IsTrue(pq.Contains(2));
			Assert.IsTrue(pq.Contains(4));
			Assert.IsTrue(pq.Contains(-5));
			Assert.AreEqual(0, pq.IndexOf(1));

			Assert.IsTrue(peek_checkPQ(pq));
			Assert.IsTrue(pop_fullcheckPQ(pq));
		}

		[Test]
		public void longRandomTest()
		{
			for (int longloop = 0; longloop < 2; longloop++)
			{

				PriorityQueue<int> pq = new PriorityQueue<int>();

				Random rnd = new Random();


				int num = rnd.Next(2000, 4000);

				for (int i = 0; i < num; ++i)
					pq.Enqueue(rnd.Next(-1000, 1000));


				Assert.AreEqual(num, pq.Count);
				Assert.IsTrue(peek_checkPQ(pq));
				Assert.AreEqual(num, pq.Count);
				Assert.IsTrue(pop_checkPQ(pq));

				//System.Diagnostics.Trace.WriteLine("loop:" + longloop.ToString());
			}
		}

		[Test]
		public void DynamicTest()
		{
			PriorityQueue<int> pq = new PriorityQueue<int>();

			Random rnd = new Random();

			int num = rnd.Next(1000);

			for (int i = 0; i < num; ++i)
				pq.Enqueue(rnd.Next(-1000, 1000));

			for (int i = 0; i < 1000; ++i)
			{
				pq.Enqueue(rnd.Next(-1000, 1000));
				int pop = pq.Dequeue();
				Assert.IsTrue(pop <= pq.Peek());
				Assert.AreEqual(num, pq.Count);
				Assert.IsTrue(peek_checkPQ(pq));
			}
		}
	}
}
